﻿/*
	Class			Clump
	
	Description		Draws a shape with a randomized rough pixel edge.
					
	History			1.00	6/20/07		Created
	
	To Do			Fix the falloff edge to be more of a gradient...
*/

package tv.digitalfx
{
	import pete.tools.Random;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class Clump extends Bitmap
	{
		public  static const EDGE_X:Number              = .1;
		public  static const EDGE_Y:Number              = .05;
		private static const MAX_EDGE:Number            = .2;
		private static const RANDOM_EDGE_CHANCE:Number  = .5;
		private static const EDGE_DEFAULT_CHANCE:Number = .004;
		private static const FALLOFF:Number             = 1.35;
		private static const MAX_BLOCK_WIDTH:int        = 10;
		private static const MAX_BLOCK_HEIGHT:int       = 10;
		private static const RANDOM_NOISE_CHANCE:Number = .1;
		
		private var shape:BitmapData;
		private var color:uint;
		private var center:Point;
		private var edgeX:Number;
		private var edgeY:Number;
		private var maxEdgeX:Number;
		private var maxEdgeY:Number;
		private var newEdgeX:Number;
		private var newEdgeY:Number;
		private var randomAlpha:uint;
		private var distanceX:Number;
		private var distanceY:Number;
		private var fillRect:Rectangle;
		private var pixelColor:uint;
		
		public function Clump ($width:Number = 100, $height:Number = 100, $color:uint = 0x000000)
		{
			shape    = new BitmapData ($width, $height, true, 0x00ffffff);
			color    = $color;
			center   = new Point ($width/2, $height/2);
			edgeX    = Math.round ($width * EDGE_X);
			edgeY    = Math.round ($height * EDGE_Y);
			maxEdgeX = Math.round ($width * MAX_EDGE);
			maxEdgeY = Math.round ($height * MAX_EDGE);
			newEdgeX = edgeX;
			newEdgeY = edgeY;
			
			for (var row:int = 0; row < shape.height; row++)
			{
				for (var col:int = 0; col < shape.width; col++)
				{
					// Check if the pixel is already filled.
					if (shape.getPixel (col, row) != $color)
					{
						randomAlpha = 255;
						distanceX   = center.x - Math.abs (col - center.x);
						distanceY   = center.y - Math.abs (row - center.y);
						fillRect    = new Rectangle (col, row, 1, 1);
						
						randomizeEdge ();
						randomizeFalloff ();
						randomizeNoise ();
						randomizeBlock ();
						
						pixelColor = (randomAlpha << 24) + $color;
						
						shape.lock ();
						shape.fillRect (fillRect, pixelColor);
						shape.unlock ();
					}
				}
			}
			
			super (shape);
		}
		
		
		private function randomizeEdge ():void
		{
			// Randomize Edge Distance
			if (Random.chance (RANDOM_EDGE_CHANCE)) { newEdgeX++; }
			if (Random.chance (RANDOM_EDGE_CHANCE)) { newEdgeX--; }
			if (Random.chance (RANDOM_EDGE_CHANCE)) { newEdgeY++; }
			if (Random.chance (RANDOM_EDGE_CHANCE)) { newEdgeY--; }
			
			// Reset to Defaults
			if (Random.chance (EDGE_DEFAULT_CHANCE)) { newEdgeX = edgeX; }
			if (Random.chance (EDGE_DEFAULT_CHANCE)) { newEdgeY = edgeY; }
			if (newEdgeX >= maxEdgeX || newEdgeX <= 0) { newEdgeX = edgeX; }
			if (newEdgeY >= maxEdgeY || newEdgeY <= 0) { newEdgeY = edgeY; }
		}
		
		
		private function randomizeFalloff ():void
		{
			if (distanceX <= newEdgeX)
			{
				var ratioX:Number = distanceX / newEdgeX;
				
				if (Random.chance (FALLOFF - ratioX))
				{
					if (Random.chance (ratioX / 5))
					{
						randomAlpha = Math.round (Random.choose (255) * ratioX);
					}
					else
					{
						randomAlpha = 0;
					}
				}
			}
			if (distanceY <= newEdgeY)
			{
				var ratioY:Number = distanceY / newEdgeY;
				
				if (Random.chance (FALLOFF - ratioY))
				{
					if (Random.chance (ratioY / 5))
					{
						randomAlpha = Math.round (Random.choose (255) * ratioY);
					}
					else
					{
						randomAlpha = 0;
					}
				}
			}
		}
		
		
		private function randomizeBlock ():void
		{
			fillRect.width  = Math.ceil ((Math.random () * MAX_BLOCK_WIDTH));
			fillRect.height = Math.ceil ((Math.random () * MAX_BLOCK_HEIGHT));
			
			// Right/Bottom Fill over extends Edge Fix
			if (fillRect.right >= shape.width)
			{
				var overRight:Number = fillRect.width - (fillRect.right - shape.width);
				fillRect.width       = Math.round (overRight / (Math.random() * 3));
			}
			if (fillRect.bottom >= shape.height)
			{
				var overLeft:Number = fillRect.height - (fillRect.bottom - shape.height);
				fillRect.height     = Math.round (overLeft / (Math.random() * 3));
			}
		}
		
		
		private function randomizeNoise ():void
		{
			if (Random.chance (RANDOM_NOISE_CHANCE))
			{
				randomAlpha = Random.choose (255);
			}
		}
			
		
	}
}